package com.alibaba.otter.node.etl.load.loader.mq.rabbit.strategy;

import com.alibaba.otter.node.etl.load.loader.mq.rabbit.MqConstants;
import com.alibaba.otter.node.etl.load.loader.mq.rabbit.MqUtils;
import com.alibaba.otter.node.etl.load.loader.mq.rabbit.exception.MqConsumeException;
import com.alibaba.otter.node.etl.load.loader.mq.rabbit.model.MessageContext;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class RetryInvoke implements RescueAction {

    private RetryStrategy strategy;

    public RetryInvoke(int maxRetry) {
        this.strategy = new DefaultRetryStrategy(maxRetry);
    }

    public RetryInvoke(RetryStrategy strategy) {
        this.strategy = strategy;
    }

    @Override
    public int handle(MqConsumeException ex) {
        MessageContext context = ex.getMsgCtx();
        int i = 0;
        int result = MqConstants.ACTION_FAIL;

        while (i < strategy.maxRetry()) {
            try {
                i = i + 1;
                context.getInvoker().invoke(ex.getMsgCtx());
                result = MqConstants.ACTION_SUCCESS;
                log.info("retry success. exit retry");
                break;
            } catch (Exception e) {
                log.error("retry failure, maxRetryTime: " + strategy.maxRetry() + ", current: " + i, e);
                MqUtils.sleep(strategy.nextRetryTime().getTime() - System.currentTimeMillis());
            } finally {
                strategy.setRetried(i);
            }
        }
        if (result == MqConstants.ACTION_SUCCESS) {
            result = result | MqConstants.BREAK_CHAIN | MqConstants.SKIP_END;
        }
        return result;
    }
}
